﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using Proggy.Data.Entities;
using Newtonsoft.Json;
using Proggy.Web.Cms.Controllers.BackEnd;
using Proggy.Web.Cms.ContentModel;

namespace Proggy.Web.Cms.ModelBinding
{
    /// <summary>
    /// Custom model binder for view models
    /// </summary>
    public class ContentModelBinder : DefaultModelBinder// IModelBinder
    {
        /// <summary>
        /// THANKYOU!! http://stackoverflow.com/questions/9417888/mvc-3-model-binding-a-sub-type-abstract-class-or-interface
        /// </summary>
        /// <param name="controllerContext"></param>
        /// <param name="bindingContext"></param>
        /// <param name="modelType"></param>
        /// <returns></returns>
        protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
        {
            //get controller
            var controller = (ContentController)controllerContext.Controller;

            // start type alias
            string typeAlias = string.Empty;

            // get type alias
            typeAlias = controllerContext.RequestContext.HttpContext.Request["TypeAlias"];

            // check
            if (string.IsNullOrEmpty(typeAlias))
            {
                // not in request so get from viewbag
                typeAlias = controllerContext.RequestContext.HttpContext.Request.Form["TypeAlias"];

                // check
                if (string.IsNullOrEmpty(typeAlias))
                {
                    throw new Exception("Request.Form[\"TypeAlias\"] and Request[\"TypeAlias\"] are both null or empty.");
                }

            }

            // get parent id
            //var parentId = Convert.ToInt32(controllerContext.RequestContext.HttpContext.Request["parentNodeId"]);

            // get type
            var availableType = controller.ContentModelTypeRepository.AvailableContentModels.Single(t => t.TypeAlias == typeAlias);

            // instantiation type
            var instantiationType = availableType.Type;

            // create model
            // http://stackoverflow.com/questions/9417888/mvc-3-model-binding-a-sub-type-abstract-class-or-interface
            var obj = Activator.CreateInstance(instantiationType, controller.ContentModelTypeRepository, controller.MembershipRepository);
            bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, instantiationType);
            bindingContext.ModelMetadata.Model = obj;
            return obj;
        }

        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            //get controller
            var controller = (ContentController)controllerContext.Controller;

            // get model
            var model = (IContentModelBase)base.BindModel(controllerContext, bindingContext);

            try
            {

                // run custom 
                model.OnAfterModelBinding(controller.ContentCrudService);

            }
            catch(Exception ex) {
                controller.ModelState.AddModelError("",ex.Message);
            }

            // return
            return model;
        } 
    }
}
